﻿using System;
using System.IO;
using Awesomium.Web;
using Awesomium.Core;
using NHTClient.Internals;
using System.Windows.Forms;
using Awesomium.Windows.Forms;
using DevExpress.XtraSplashScreen;
using DevExpress.XtraEditors;
using Awesomium.Core.Data;

namespace NHTClient
{
    public partial class WebDocument : UserControl
    {
        private WebControl webControl;
        private WebSession webSession;
        private WebSession chatSession;
        private Boolean isLoading;

        private String USER_DATA = String.Format("{0}{1}UserData", Path.GetDirectoryName(Application.ExecutablePath), Path.DirectorySeparatorChar);
        private String PROFILE_DATA = String.Format("{0}{1}UserData{2}Profiles", Path.GetDirectoryName(Application.ExecutablePath), Path.DirectorySeparatorChar, Path.DirectorySeparatorChar);
        private String ASSETS_DATA = String.Format("{0}{1}UserData{2}Assets", Path.GetDirectoryName(Application.ExecutablePath), Path.DirectorySeparatorChar, Path.DirectorySeparatorChar);
        private String CHILD_PROCESS = String.Format("{0}{1}Core{2}WebProcess", Path.GetDirectoryName(Application.ExecutablePath), Path.DirectorySeparatorChar, Path.DirectorySeparatorChar);
        private const String NHT_CAPTION_DEFAULT = "Ngũ Hành Tướng";
        private const String NHT_CUSTOM_CSS = "body{overflow:hidden}.playgate-nav,.mainBG .blurBG #sideBar,.content nav,.loginform,footer,main .rightside,.container header,aside,main .headcontent,main .content .content-top,main .content .primary .breadcrumb,main .content .content-bot{display:none !important}main,.mainBG{margin-top:0px !important}.mainBG{height:100% !important}.mainBG .blurBG{position:inherit!important}.mainBG .blurBG .gamescreen{width:100% !important;height:100% !important;left:0px !important}.outertop{margin-top:0px !important;background:#ccc !important}.outertop .outerbot,main .content,main .content .primary{background:#ccc !important}";

        public WebControl Browser { get; private set; }

        private Boolean IsLoading
        {
            get
            {
                return isLoading;
            }
            set
            {
                if (isLoading != value)
                {
                    isLoading = value;
                    switch (IsLoading)
                    {
                        case false:
                            SplashScreenManager.CloseForm();
                            ResumeLayout();
                            UseWaitCursor = false;
                            break;

                        case true:
                            SuspendLayout();
                            UseWaitCursor = true;
                            SplashScreenManager.ShowForm(typeof(NHTWait));
                            break;
                    }
                }
            }
        }

        public WebDocument(string url)
        {
            webSession = InitializeWebSession();

            InitializeComponent();

            webControl = CreateWebBrowser(url, webSession);
            browserPanel.Controls.Add(webControl);

            InitialiseWebBrowser();

        }

        public WebDocument(string url, string identifier)
        {
            if (identifier == "9ilEmXMF5IeZQCM")
            {
                chatSession = InitializeChatSession();

                InitializeComponent();

                webControl = CreateWebBrowser(url, chatSession);
                browserPanel.Controls.Add(webControl);

                InitialiseWebBrowser();
            }
            else
            {
                webSession = InitializeWebSession(identifier);

                InitializeComponent();

                webControl = CreateWebBrowser(url, webSession);
                browserPanel.Controls.Add(webControl);

                InitialiseWebBrowser();
            }
        }

        public WebDocument(IntPtr nativeView)
        {
            InitializeComponent();

            InitialiseWebBrowser();
            webControl.NativeView = nativeView;
        }

        private WebControl CreateWebBrowser(String source = null, WebSession session = null)
        {
            var browser = new WebControl() { Source = new Uri(source), WebSession = session, ViewType = WebViewType.Window, Dock = DockStyle.Fill };
            browser.Update();

            return browser;
        }

        private WebSession InitializeWebSession(String _profileIndentifier = null)
        {
            // Build a data path string. In this case, a Cache folder under our executing directory.
            // - If the folder does not exist, it will be created.
            // - The path should always point to a writeable location.
            string dataPath;
            if (!String.IsNullOrEmpty(_profileIndentifier))
            {
                dataPath = String.Format("{0}{1}{2}", PROFILE_DATA, Path.DirectorySeparatorChar, _profileIndentifier);
            }
            else
            {
                dataPath = String.Format("{0}{1}{2}", PROFILE_DATA, Path.DirectorySeparatorChar, GenerateRandomString());
            }

            // Check if a session synchronizing to this data path, is already created;
            // if not, create a new one.
            var session = WebCore.Sessions[dataPath] ?? WebCore.CreateWebSession(dataPath, new WebPreferences()
            {
                CustomCSS = NHT_CUSTOM_CSS,
                DefaultEncoding = "utf-8",
                SmoothScrolling = true,
                WebGL = true,
                EnableGPUAcceleration = true
            });

            // Return the session.
            return session;
        }

        private WebSession InitializeChatSession()
        {
            // Build a data path string. In this case, a Cache folder under our executing directory.
            // - If the folder does not exist, it will be created.
            // - The path should always point to a writeable location.
            string dataPath = String.Format("{0}{1}{2}", PROFILE_DATA, Path.DirectorySeparatorChar, "9ilEmXMF5IeZQCM");

            // Check if a session synchronizing to this data path, is already created;
            // if not, create a new one.
            var session = WebCore.Sessions[dataPath] ?? WebCore.CreateWebSession(dataPath, WebPreferences.Default);

            session.AddDataSource("chat", new DirectoryDataSource(String.Format("{0}{1}chat{2}", ASSETS_DATA, Path.DirectorySeparatorChar, Path.DirectorySeparatorChar)));

            // Return the session.
            return session;
        }

        private void InitialiseWebBrowser()
        {
            Browser = webControl;

            // Set the source for our data bindings.
            webControlBindingSource.DataSource = webControl;
            // Setup handlers
            webControl.TitleChanged += OnTitleChanged;
            webControl.DocumentReady += OnDocumentReady;
            webControl.LoadingFrame += OnLoadingFrame;
            webControl.ShowJavascriptDialog += OnJavascriptDialog;
            webControl.ShowCreatedWebView += Program.OnShowNewView;
        }

        private void OnJavascriptDialog(object sender, JavascriptDialogEventArgs e)
        {
            if (e.DialogFlags.HasFlag(JSDialogFlags.HasPromptField))
            {
                // It's a 'window.prompt' dialog.
            }
            else
            {
                e.Handled = true;
                e.Cancel = true;

                if (XtraMessageBox.Show(e.Message,
                 String.Format("{0} - {1}", NHT_CAPTION_DEFAULT, e.FrameURL),
                 e.DialogFlags.GetMessageBoxButtons(),
                 e.DialogFlags.GetMessageBoxIcon()) == DialogResult.OK)
                {
                    e.Cancel = false;
                }
            }
        }

        private void OnLoadingFrame(object sender, LoadingFrameEventArgs e)
        {
            this.InvokeOnUiThreadIfRequired(() => IsLoading = true);
        }

        private void OnDocumentReady(object sender, DocumentReadyEventArgs e)
        {
            if (webControl == null && !webControl.IsLive)
                return;

            if (e.ReadyState == DocumentReadyState.Loaded && webControl.IsDocumentReady)
            {
                IsLoading = false;
            }
        }

        private void OnTitleChanged(object sender, TitleChangedEventArgs e)
        {
            this.InvokeOnUiThreadIfRequired(() => Parent.Text = e.Title);
        }

        private String GenerateRandomString()
        {
            var chars = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789";
            var stringChars = new char[22];
            var random = new Random();

            for (int i = 0; i < stringChars.Length; i++)
            {
                stringChars[i] = chars[random.Next(chars.Length)];
            }

            var finalString = new String(stringChars);

            return finalString;
        }

        private string JsGetImgBase64String(string getElementQuery, bool leaveOnlyBase64Data = true)
        {
            string data = webControl.ExecuteJavascriptWithResult(@"
                        function getImgBase64String(img)
                        {
                           var cnv = document.createElement('CANVAS');
                           var ctx = cnv.getContext('2d');
                           ctx.drawImage(img, 0, 0);
                           return cnv.toDataURL();
                        }
                 " + String.Format("getImgBase64String({0});", getElementQuery));

            // delete "header" like data:image/png;base64 etc.           
            if (leaveOnlyBase64Data && data.Contains(","))
            {
                data = data.Substring(data.IndexOf(",") + 1);
            }

            return data;
        }
    }
}
